package com.huifer.planar.aset.utils.shptools.polygontools;

import com.huifer.planar.aset.utils.shptools.overlay.Operation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.ParseException;

/**
 * <p>Title : PolygonNodeTriangle </p>
 * <p>Description : 多边形自身节点组成三角形</p>
 *
 * @author huifer
 * @date 2018/10/15
 */
public class PolygonNodeTriangle {
    private int num = 3;
    private Set resultP = new HashSet();

    public static void main(String[] args) {
        //0
        double[] point1 = new double[]{0, 0};
        //1
        double[] point2 = new double[]{10, 0};
        //2
        double[] point3 = new double[]{20, 0};
        //3
        double[] point4 = new double[]{10, 10};

        List<double[]> allPoint = new ArrayList();
        allPoint.add(point1);
        allPoint.add(point3);
        allPoint.add(point4);


        PolygonNodeTriangle polygonCenterPoint = new PolygonNodeTriangle();

        // 外围
        Polygon waiwei = polygonCenterPoint.waiwei(point1, point3, point4);
        // 节点三角形
        List<Polygon> sanjiaoxing = polygonCenterPoint.triangleMothed(allPoint);
        // 外围内所有三角形
        List<Polygon> rangeTriangle = polygonCenterPoint.getRangeTriangle(waiwei, sanjiaoxing);
        // 重心xy
        double[] gravityCenterXY = polygonCenterPoint.getGravityCenterXY(rangeTriangle);

//        System.out.println(rangeTriangle.size());
//        System.out.println("================================================");

        long l = System.nanoTime();
        double[] doubles = polygonCenterPoint. polygonGravityPoint("POLYGON((120.37980313403132 30.172333703377657, 120.37980942517527 30.172326622745672, 120.37985277175497 30.172298946215204, 120.37987121126392 30.17229507125022, 120.37995190686375 30.172278129869035, 120.38002279118274 30.172263249798206, 120.38003282230744 30.17226226289911, 120.38011530377118 30.172254127759, 120.38019779475735 30.172246001964744, 120.38028027558778 30.17223786682597, 120.38036275707434 30.172229741051698, 120.38044523790478 30.172221605912924, 120.38052772889095 30.172213480118668, 120.38061021035469 30.17220534497855, 120.38069269120795 30.17219721920562, 120.38073393637228 30.172193151350772, 120.38072792481294 30.172170209851867, 120.3806900481962 30.172168809200393, 120.38065722486091 30.172167190211958, 120.38064503115974 30.172166430791155, 120.38060363425313 30.172163845875946, 120.38058618797979 30.172162348237652, 120.3805448824488 30.17215879734133, 120.38051376312399 30.172158384619806, 120.38048587333799 30.17215445344297, 120.38043344510261 30.172147053432987, 120.3804035751215 30.172148127259177, 120.38040027522464 30.172148242737904, 120.38038263414909 30.172139055009826, 120.38037536414059 30.17214051430967, 120.38036588167937 30.172145228230324, 120.38035211169534 30.172149156725908, 120.3803261590655 30.17215270426967, 120.38030442857391 30.17215567491419, 120.38030483281695 30.1721726439591, 120.38027400432011 30.17217644582816, 120.38027415262493 30.172177790348055, 120.38024594724831 30.172180792248742, 120.3802492416233 30.17220413668994, 120.38017047387494 30.172190438179115, 120.38012978228303 30.172183356702046, 120.38012968054034 30.172196959497914, 120.38009734828904 30.17219700991051, 120.38005584385508 30.172197079074813, 120.38004789961659 30.17219863896184, 120.37996691134396 30.172214506635964, 120.37995338714782 30.172217161954755, 120.37988426537076 30.17221880596284, 120.37981303669099 30.172220499030566, 120.37980148370106 30.172218618761757, 120.37974921927679 30.17221009064338, 120.37972207977158 30.1721993246425, 120.37972161256262 30.17219913610414, 120.37968783074818 30.17217895207701, 120.37966037535297 30.172162003598956, 120.37966003220633 30.1721617878037, 120.379618492148 30.17213450698362, 120.37959479407878 30.17211777648165, 120.37954363467553 30.172081660729223, 120.37953087904486 30.172071731078336, 120.37951682393945 30.172060793747626, 120.37950468623484 30.172049229274464, 120.37947644811506 30.172017488189777, 120.37945793835046 30.17199669409229, 120.37943894907896 30.171970665469914, 120.37943180797281 30.171956933020603, 120.3794147006354 30.171924040196828, 120.3794090253541 30.171877448009404, 120.37945780112933 30.171872308715354, 120.37948016598439 30.17186977032156, 120.37954206377648 30.171862744007363, 120.37956237260458 30.17185982153135, 120.37960418324869 30.171853387874037, 120.37961851525681 30.171848274236666, 120.3796322021742 30.171841964775425, 120.37965512008374 30.17182364699422, 120.37966732072839 30.171805947327854, 120.37966839435184 30.171799517862336, 120.37967290515815 30.171772645887433, 120.37967410252688 30.171727600586063, 120.37967506267614 30.171691501864213, 120.37967454399794 30.171691502955763, 120.37967402532377 30.171691505700103, 120.37967429972406 30.171672349117475, 120.37967554104341 30.171645077433205, 120.37967649063137 30.171621795682213, 120.37967795937027 30.1715857140709, 120.37967844885516 30.171573734615013, 120.3796799175927 30.171537652452763, 120.37968013286763 30.17153243464658, 120.37968159114777 30.171496479221354, 120.37968012736474 30.17146625250596, 120.37967845268899 30.171460451931512, 120.37965824596398 30.171390412786966, 120.37963804939336 30.171320382436008, 120.37961784203374 30.171250342741864, 120.37959763533021 30.171180312412236, 120.37958753671684 30.171145292554503, 120.37957996931719 30.171109961050103, 120.37957198500996 30.17108234736769, 120.37955681797747 30.171029901087948, 120.37955173653101 30.17101232649187, 120.37953147791784 30.170942305086438, 120.37951208720708 30.170875251944366, 120.37951137437753 30.170872247543898, 120.37950292536928 30.170836899163035, 120.3794933151642 30.17079803330305, 120.37948782357613 30.170728847441282, 120.37948496569503 30.170692828926864, 120.37948385654624 30.170676366572685, 120.37947959405497 30.170613352451305, 120.37947893929524 30.17060429150168, 120.37947375162092 30.17053221644885, 120.37946856460273 30.17046015076053, 120.37946597583272 30.17042411349892, 120.37946575236533 30.17042181216335, 120.37945883726172 30.17035165469356, 120.37945870812169 30.17034985836675, 120.37945353123642 30.170277792657103, 120.37944836446121 30.17020571756029, 120.37944318757594 30.170133651850644, 120.37944298026068 30.170095361763078, 120.3794368250769 30.170060523128075, 120.37944115151649 30.170060126165037, 120.37944387984167 30.17005987691013, 120.37943569981778 30.1699904168312, 120.37943384571633 30.169974660139513, 120.3794380455257 30.169918407462895, 120.37944342149622 30.169846346540808, 120.37944393369793 30.169839530398644, 120.37946506655253 30.169803903246006, 120.37948880726887 30.16979967389233, 120.37949364203803 30.169799447200262, 120.37953508992058 30.169797482388102, 120.37953886725323 30.169780703430646, 120.37953784669473 30.169774865117912, 120.3795375629936 30.16976499957344, 120.37953812049247 30.169751043771075, 120.37953909393701 30.169741708334982, 120.37953990131389 30.169736732795936, 120.37954154720664 30.169726565685856, 120.37954511599541 30.16971776635689, 120.37955619600326 30.16970435642397, 120.37955324031766 30.169683556589078, 120.37954390752121 30.169617933442776, 120.37954305241104 30.169611898649052, 120.37953911480221 30.169584222458834, 120.37954656457352 30.169579864863305, 120.37953785498705 30.169544138538576, 120.37932037323533 30.169583401321134, 120.37933585745327 30.169601764449993, 120.37933774129648 30.16960399893383, 120.3793455204305 30.169641235125393, 120.37934507874897 30.16967282886364, 120.3793447613712 30.16969591921163, 120.37934425822927 30.169740493655514, 120.37934426929458 30.16974503388642, 120.37934431403194 30.169759232485543, 120.37934432948872 30.169761416909743, 120.3793452624283 30.1697780779713, 120.37934556050776 30.169781110240418, 120.37934642205545 30.16979394410773, 120.37934698209173 30.169802337523645, 120.37934672447692 30.16982006604778, 120.37934413871908 30.169866079508864, 120.37934209051484 30.169902686278704, 120.37934185547131 30.16993825127151, 120.37934157488584 30.169980595613634, 120.3793436810961 30.170010405572167, 120.37934877504101 30.17008248082225, 120.37935385885169 30.170154555542723, 120.37935640582481 30.170190593443234, 120.37936191259581 30.170231968081207, 120.3793645019875 30.170251369863344, 120.37936676891334 30.170273064764068, 120.37936998384275 30.17030382936318, 120.37937749474484 30.170375745816003, 120.37938125556825 30.17041169962363, 120.37938512254146 30.170431441398613, 120.37938770660091 30.17045307282536, 120.37939627617162 30.170524896696925, 120.37940484574234 30.170596720568486, 120.37941341467975 30.170668544441384, 120.37941769407128 30.170704451981035, 120.37942405737515 30.17076517805629, 120.37942576357625 30.1707753386629, 120.37943134340198 30.170808489893375, 120.37943431041802 30.170808213140344, 120.37944504881047 30.170846147198965, 120.37945112346263 30.170894976443336, 120.3794515259106 30.17089821619525, 120.37946202680848 30.17096655189031, 120.3794660610035 30.170992801506905, 120.3794730238837 30.171038127140033, 120.37947851703824 30.17107391477622, 120.37948321860297 30.171117777477768, 120.37948470713418 30.171131653496236, 120.3794862250615 30.171141480081605, 120.37949174924805 30.171177267652492, 120.3794923998591 30.171180208826392, 120.3795080020459 30.171251133647516, 120.37951580851097 30.171286591363824, 120.37952418836561 30.171318251381315, 120.37952576782156 30.17132422019129, 120.37953859646663 30.171372683725586, 120.37953975125353 30.171395139053153, 120.37954325871665 30.171463299944147, 120.37954086992181 30.171466698730068, 120.3795232394147 30.171491730645908, 120.37947458148425 30.17149844922221, 120.37939259608775 30.17150977874056, 120.3793472885168 30.171516039050438, 120.37931050539761 30.171520521183925, 120.37926254260026 30.171526361209033, 120.37922829893184 30.171530533331325, 120.37918719031514 30.17153553914088, 120.37916505517485 30.171534367055884, 120.37916103882773 30.171534150175837, 120.37913654116049 30.17152662637628, 120.37911159096984 30.171518963040654, 120.37908576176564 30.171513646884605, 120.37907823554173 30.171512100823048, 120.37904371349556 30.171507552232303, 120.3790147941727 30.171507351398322, 120.37900654148883 30.17150994108078, 120.37900530137988 30.171511983802365, 120.37900419561473 30.17151380035792, 120.3790059718921 30.171518932985506, 120.379012270548 30.171526887901035, 120.37901308050482 30.17152790818067, 120.37902832089367 30.171539772995022, 120.37900481044177 30.171557667803373, 120.37894259733582 30.171562645854397, 120.37893230439195 30.17156716314414, 120.37890755259824 30.17157801961733, 120.37889889076706 30.17158735360355, 120.3788968827417 30.17158951473938, 120.37887914472849 30.17160863424852, 120.37882618337964 30.171620778121902, 120.37882433769109 30.171621206225954, 120.37877386836583 30.171621375795045, 120.37874332652137 30.171619363596182, 120.37870473149665 30.171616827327032, 120.3786674073218 30.171637594580876, 120.37866363536266 30.17163968780734, 120.37865340750776 30.17167065203723, 120.3786488124034 30.171689180831983, 120.37864838282056 30.171690918282717, 120.37864632928466 30.17170402934471, 120.37864609120903 30.171712884470843, 120.3786447684712 30.171761838367964, 120.37864885041073 30.171784810923516, 120.37864904825537 30.171785953696993, 120.37865051228842 30.17179419535618, 120.37865398426227 30.171801020743654, 120.37866688838226 30.171816528297526, 120.37868925433837 30.171814441668005, 120.3787263768765 30.17181306333817, 120.37874586249771 30.1718127788179, 120.37874765787795 30.171812756858714, 120.37880030643902 30.171812853763427, 120.37880271387954 30.1718129478653, 120.37881401593366 30.17181398903746, 120.37882868171029 30.171815637423116, 120.37886295315225 30.17181948299743, 120.37891090549789 30.171825465505528, 120.37894857230941 30.171830170554895, 120.3789915102031 30.171835153201265, 120.37899313939694 30.1718352847517, 120.37900845777803 30.171836534539935, 120.37902110890836 30.17183762741555, 120.37903636656675 30.171839427715494, 120.37907292196344 30.171843891039675, 120.37907549577078 30.171844165498058, 120.37915787312967 30.171853081460085, 120.37917742095732 30.171855193926493, 120.37918146444173 30.171855631674305, 120.37918477762553 30.171856030740784, 120.37923196991133 30.171861717343578, 120.3792400869388 30.17186297292101, 120.37924309694587 30.171863445348908, 120.37924624001181 30.171863943941666, 120.37926165694797 30.17186639400955, 120.37926970149248 30.171867532390397, 120.37928763730835 30.17187006695974, 120.37932198356111 30.171874725005534, 120.37933976390937 30.171877133737976, 120.3793443205204 30.171877891050016, 120.37936271626917 30.17188152652116, 120.379373055386 30.171883481517003, 120.37938045425601 30.17192709998734, 120.37938369942715 30.17192947595122, 120.37937731140964 30.171952417099895, 120.37937512216442 30.17196519403002, 120.37937246218262 30.17198075251905, 120.37937059786948 30.172011997203825, 120.37936823651604 30.172022237992042, 120.37936444129002 30.172036092624904, 120.37936437032566 30.17203659853245, 120.37935853287104 30.172076778927117, 120.37935265877404 30.172097506990777, 120.37934579720245 30.172104923240674, 120.37934503091027 30.17210544824144, 120.37933538659696 30.172112094080344, 120.37931828059226 30.172122364245546, 120.37933923994821 30.172202903726543, 120.37935303210739 30.172199758613665, 120.37936519694132 30.172196988806498, 120.37939634164532 30.17219508203884, 120.37943516007164 30.172199892647896, 120.3794629144083 30.172203336532434, 120.37951540039518 30.172217542119228, 120.37952554448982 30.172220291973563, 120.3795551253837 30.172236766031112, 120.37958034554696 30.172260615264832, 120.37958085528057 30.172261101769465, 120.37959898296523 30.172284154953033, 120.37961036334879 30.172298626099494, 120.37962512159146 30.172321323858842, 120.37963700817167 30.172339609625464, 120.37980313403132 30.172333703377657))");


//        System.out.println(System.nanoTime() - l);
    }

    /***
     * polygon wkt 计算重心
     * @param wkt
     * @return
     */
    private double[] polygonGravityPoint(String wkt) {

        if (!wkt.startsWith("POLYGON")) {
            return null;
        }

        Operation operation = new Operation();
        // 外围数据转 list<double[]>
        Polygon waiwei = null;
        try {
            waiwei = operation.createPolygonByWKT(wkt);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Coordinate[] coordinates = waiwei.getCoordinates();
        List<double[]> allP = new ArrayList<>();
        Arrays.stream(coordinates).forEach(
                s -> {
                    double nowX = s.x;
                    double nowY = s.y;
                    allP.add(new double[]{nowX, nowY});
                }
        );

        List<Polygon> polygons = triangleMothed(allP);
        List<Polygon> rangeTriangle1 = getRangeTriangle(waiwei, polygons);
        double area = waiwei.getArea();
        double[] gravityCenterXY1 = getGravityCenterXY(rangeTriangle1);
        return gravityCenterXY1;
    }


    /***
     * 重心值
     * @param rangeTriangle
     * @return [x, y]
     */
    private double[] getGravityCenterXY(List<Polygon> rangeTriangle) {
        double xArea = 0.0;
        double yArea = 0.0;
        double aArea = 0.0;
        for (Polygon triangle : rangeTriangle) {
            Coordinate[] coordinates = triangle.getCoordinates();
            double area = triangle.getArea();
            double[] oneGR = triangleCenterOfGravity(coordinates[0], coordinates[1], coordinates[2]);
            xArea += oneGR[0] * area;
            yArea += oneGR[1] * area;
            aArea += area;
        }
//        System.out.println("重心X  " + xArea / aArea);
//        System.out.println("重心Y  " + yArea / aArea);
        return new double[]{xArea / aArea, yArea / aArea};
    }

    /***
     * 范围内三角形
     * @param waiwei
     * @param sanjiaoxing
     * @return
     */
    private List<Polygon> getRangeTriangle(Polygon waiwei, List<Polygon> sanjiaoxing) {

        List<Polygon> triangle = new ArrayList<>();
        // 判断三角形是否在面内
        for (int i = 0; i < sanjiaoxing.size(); i++) {
            Polygon polygon = sanjiaoxing.get(i);
            boolean within = polygon.within(waiwei);
            if (within) {
                triangle.add(polygon);
            }
        }
        return triangle;
    }


    /***
     * 三角形重心计算
     * @param a
     * @param b
     * @param c
     * @return
     */
    private double[] triangleCenterOfGravity(Coordinate a, Coordinate b, Coordinate c) {

        double gravityX = (a.x + b.x + c.x) / 3;
        double gravityY = (a.y + b.y + c.y) / 3;
        double[] result = new double[]{gravityX, gravityY};
        return result;
    }


    /***
     * 测试用外包图形
     * @return
     */
    private Polygon waiwei(double[] point1, double[] point3, double[] point4) {
        List<double[]> ceshimian = new ArrayList();
        ceshimian.add(point1);
//        ceshimian.add(point2);
//        ceshimian.add(point7);
        ceshimian.add(point4);
//        ceshimian.add(point6);
//        ceshimian.add(point5);
        ceshimian.add(point3);
        String polygonForList = createPolygonForList(ceshimian);
        Operation op = new Operation();
        Polygon polygonByWKT = null;
        try {
            polygonByWKT = op.createPolygonByWKT(polygonForList);
            return polygonByWKT;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 生成所有三角形
     * @param allPoint
     * @return
     */
    private List<Polygon> triangleMothed(List<double[]> allPoint) {
        // 索引 -> 点坐标
        Map<String, double[]> indexOfPoint = new HashMap();
        for (int i = 0; i < allPoint.size(); i++) {
            indexOfPoint.put(String.valueOf(i), allPoint.get(i));
        }
        // 排序结果
        sort((List) indexOfPoint.keySet().stream().collect(Collectors.toList()), new HashSet());

        // 删除元素相同后的集合


        // 所有三角形
        List<Polygon> allTriangle = new ArrayList();


        for (Object oneDataObj : resultP) {
            //这一行数据
            Set oneDataList = (Set) oneDataObj;
            // 这一行数据的三角形数据
            List<double[]> trianglePoint = new ArrayList();

            oneDataList.forEach(
                    s -> trianglePoint.add(indexOfPoint.get(s)
                    ));
            Polygon triangle = createTriangle(trianglePoint);
            if (triangle != null) {
                allTriangle.add(triangle);
            }
        }
        // 所有三角形结束


        return allTriangle;


    }

    /***
     * 从点坐标集合中创建一个面
     * @param points
     * @return
     */
    private static String createPolygonForList(List<double[]> points) {
        String end = "))";
        String res = "POLYGON((";
        Operation op = new Operation();
        for (double[] point : points) {
            String x = Double.toString(point[0]);
            String y = Double.toString(point[1]);
            res += x + " " + y + ", ";
        }
        res += Double.toString(points.get(0)[0]) + " " + Double.toString(points.get(0)[1]);
        res += end;
        try {
            op.createPolygonByWKT(res);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return res;
    }

    /***
     * 创建三角形
     * @param trianglePoint
     * @return polygon
     */
    private static Polygon createTriangle(List<double[]> trianglePoint) {
        Operation op = new Operation();

        String triangleWkt;
        boolean isTri = isTriangle(trianglePoint);
        if (isTri) {
            triangleWkt = "POLYGON((" + trianglePoint.get(0)[0] + " " + trianglePoint.get(0)[1] + ", " + trianglePoint.get(1)[0] + " " + trianglePoint.get(1)[1] + ", " + trianglePoint.get(2)[0] + " " + trianglePoint.get(2)[1] + ", " + trianglePoint.get(0)[0] + " " + trianglePoint.get(0)[1] + "))";
            try {
                Polygon polygonByWKT = op.createPolygonByWKT(triangleWkt);

                return polygonByWKT;
//                return triangleWkt;
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /***
     * 判断三角形
     * @param trianglePoint
     * @return
     */
    private static boolean isTriangle(List<double[]> trianglePoint) {
        double[] doubles = trianglePoint.get(0);
        double[] doubles1 = trianglePoint.get(1);
        double[] doubles2 = trianglePoint.get(2);
        double len = Math.sqrt(Math.pow(doubles[0] - doubles1[0], 2) + Math.pow(doubles[1] - doubles1[1], 2));
        double len1 = Math.sqrt(Math.pow(doubles[0] - doubles2[0], 2) + Math.pow(doubles[1] - doubles2[1], 2));
        double len2 = Math.sqrt(Math.pow(doubles1[0] - doubles2[0], 2) + Math.pow(doubles1[1] - doubles2[1], 2));
        if ((len + len1 > len2) && (len + len2 > len1) && (len1 + len2 > len)) {
            return true;
        }
        return false;
    }


    /***
     * 不重复排列 (元素不相同)
     * @param datas
     * @param target
     */
    private void sort(List datas, Set target) {
        if (target.size() == this.num) {
            this.resultP.add(target);
            return;
        }
        for (int i = 0; i < datas.size(); i++) {
            List newDatas = new ArrayList(datas);
            Set newTarget = new HashSet(target);
            newTarget.add(newDatas.get(i));
            newDatas.remove(i);
            sort(newDatas, newTarget);
        }
    }
}
